﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text.RegularExpressions;
using MobileBank1.Model;

namespace MobileBank1
{
	public class RecordConverter
	{
		public Regex RecordHeadeRegex = new Regex(UsefulResource.HeaderPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline);
		public Regex TableHeadeRegex = new Regex(UsefulResource.TableHeaderPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline);
		public Regex TableRowRegex = new Regex(UsefulResource.TableRowPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline);
		public Regex TableRowDataRegex = new Regex(UsefulResource.TableRowDataPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline);

		public void ConevrtHeader(MobileRecord currentRecord, List<string> rawRecord)
		{
			var headerString = rawRecord.FirstOrDefault(x => RecordHeadeRegex.IsMatch(x));
			
			if (string.IsNullOrEmpty(headerString))
				return;
			
			var matchResult = RecordHeadeRegex.Match(headerString);

			var gosb = matchResult.Groups["GOSB"] != null ? matchResult.Groups["GOSB"].Value : null;
			var osb = matchResult.Groups["OSB"] != null ? matchResult.Groups["OSB"].Value : null;
			var vsp = matchResult.Groups["VSP"] != null ? matchResult.Groups["VSP"].Value : null;

			currentRecord.Gosb = gosb;
			currentRecord.Osb = osb;
			currentRecord.Vsp = vsp;
		}

		public void ConevrtBody(MobileRecord currentRecord, List<string> rawRecord)
		{
			var raw = rawRecord.Where(x => !RecordHeadeRegex.IsMatch(x)).ToList();

			if (raw.Count == 0)
				return;

			if (!IsTableExist(raw))
				return;

			FillTable(rawRecord, currentRecord.Table);
		}

		private bool IsTableExist(IEnumerable<string> raw)
		{
			return raw.Any(x => TableHeadeRegex.IsMatch(x));
		}

		private void FillTable(List<string> rawRecord, DataTable currentRecord)
		{
			var tStartIdx = rawRecord.FindIndex(x => TableHeadeRegex.IsMatch(x));
			var first = tStartIdx + 2;

			List<string> rawRow;
			var isBreak = GetNextRow(rawRecord, ref first, out rawRow);
			while (!isBreak)
			{
				var row = currentRecord.NewRow();
				currentRecord.Rows.Add(row);
				FillRow(rawRow, row);

				isBreak = GetNextRow(rawRecord, ref first, out rawRow);
			}
		}

		private bool GetNextRow(List<string> rawRecord, ref int rowIndex, out List<string> rawRow)
		{
			rawRow = new List<string>();

			while (!string.IsNullOrEmpty(rawRecord[rowIndex]) || !string.IsNullOrWhiteSpace(rawRecord[rowIndex]))
			{
				if (TableRowDataRegex.IsMatch(rawRecord[rowIndex]))
					rawRow.Add(rawRecord[rowIndex]);
				else if (string.IsNullOrEmpty(rawRecord[rowIndex]) || string.IsNullOrWhiteSpace(rawRecord[rowIndex]))
					return true;

				rowIndex++;
			}

			return false;
		}

		private void FillRow(List<string> rawRow, DataRow row)
		{
			var ci = 2;

			foreach (var match in rawRow.Select(s => TableRowDataRegex.Match(s)))
			{
				if (match.Groups["Phone"].Success)
				{
					row["Phone"] = match.Groups["Phone"];
					row["CardMonitoring"] = match.Groups["Card"];
					row["Card"] = match.Groups["PayCard"];
					row["RegistrationDate"] = match.Groups["Date"];
					row["Tarif"] = match.Groups["Tarif"];
					row["Operator"] = match.Groups["Orerator"];
					row["Email"] = match.Groups["Email"];
				}
				else
				{
					try
					{
						row[string.Format("Card{0}", ci)] = match.Groups["Card"];
						ci++;
					}
					catch (Exception e)
					{
						Console.WriteLine("\nFatal error has been cought in {0}\n\tMessage:{1}\n\tci is {2}", e.Source, e.Message, ci);
						row.AcceptChanges();
						throw;
					}
				}
			}

			row.AcceptChanges();
		}
	}
}
